	//---------------------------------------------------------------------
	// Includes
	//---------------------------------------------------------------------		
	#include <Geometry/Mesh.hpp>
	#include <Rendering/Renderer.hpp>
	
namespace Geometry {
	
	//---------------------------------------------------------------------			
	// IBuffer methods
	//---------------------------------------------------------------------		
	IBuffer::IBuffer(Rendering::VertexBufferType t, int nElt):
	bufferID(0),
	type(t),	
	nElements(nElt) {
		// Create vertex buffer
		bufferID = Rendering::Renderer::Instance().CreateVertexBuffer(type, nElements);
	}
	//---------------------------------------------------------------------		
	IBuffer::IBuffer(const IBuffer& copy):
	bufferID(copy.bufferID),
	type(copy.type),	
	nElements(copy.nElements) {
	
	}
	//---------------------------------------------------------------------	
	IBuffer& IBuffer::operator=(const IBuffer& copy) {
		bufferID  = copy.bufferID;		
		type	  = copy.type;
		nElements = copy.nElements;
		return *this;
	}
	//---------------------------------------------------------------------		
	IBuffer::~IBuffer() {
		Rendering::Renderer::Instance().DeleteVertexBuffer(bufferID);
	}
	//---------------------------------------------------------------------		
	void IBuffer::Load(void* data) {
		Rendering::Renderer::Instance().LoadVertexBuffer(bufferID, type, nElements, data);
	}
	//---------------------------------------------------------------------		
	Rendering::VertexBufferType IBuffer::GetType() const{
		return type;
	}
	//---------------------------------------------------------------------		
	void IBuffer::Enable(int location) const {
		Rendering::Renderer::Instance().EnableVertexBuffer(bufferID, type, nElements, location);
	}
	//---------------------------------------------------------------------	
	void IBuffer::Disable(int location) const {
		Rendering::Renderer::Instance().DisableVertexBuffer(type, location);
	}
	//---------------------------------------------------------------------	
	int IBuffer::GetNumberOfElements() const {
		return nElements;
	}
	//---------------------------------------------------------------------	
	TIBufferPointer IBuffer::CreateBuffer(Rendering::VertexBufferType type, int nElt) {
		return TIBufferPointer(new IBuffer(type, nElt));
	}



	//---------------------------------------------------------------------			
	// Mesh methods
	//---------------------------------------------------------------------	
	Mesh::Mesh(Rendering::MeshType t, bool i):	
	meshType(t),
	indexed(i),
	nElements(0) {		
	}	
	//---------------------------------------------------------------------		
	Mesh::~Mesh() {	
		buffers.clear();
	}
	//---------------------------------------------------------------------		
	Rendering::MeshType Mesh::GetMeshType() const {
		return meshType;
	}
	//---------------------------------------------------------------------		
	void Mesh::AddBuffer(const TIBufferPointer& buffer) {
		// Get information of number of elements & index type
		if(indexed) {
			if(buffer->GetType() == Rendering::INDEX_BUFFER)
				nElements = buffer->GetNumberOfElements();				
		}
		else {
			if(buffer->GetType() == Rendering::VERTEX_BUFFER)
				nElements = buffer->GetNumberOfElements();
		}
		// Add buffers to mesh
		buffers[buffer->GetType()] = buffer;
	}
	//---------------------------------------------------------------------		
	int Mesh::GetNumberOfElements() const {
		return nElements;
	}
	//---------------------------------------------------------------------		
	bool Mesh::IsIndexed() const {
		return indexed;
	}
	//---------------------------------------------------------------------		
	void Mesh::Enable(Rendering::VertexBufferType type, int location) const {
		TIBufferMap::const_iterator it;
		it = buffers.find(type);
		assert(it!=buffers.end());
		it->second->Enable(location);
	}
	//---------------------------------------------------------------------		
	void Mesh::Disable(Rendering::VertexBufferType type, int location) const {
		TIBufferMap::const_iterator it;
		it = buffers.find(type);
		assert(it!=buffers.end());
		it->second->Disable(location);
	}
	//---------------------------------------------------------------------		
	TMeshPointer Mesh::CreateMesh(Rendering::MeshType type, bool indexed) {
		return TMeshPointer(new Mesh(type, indexed));
	}
	//---------------------------------------------------------------------		
	void Mesh::Render() {
		if(indexed) {
			buffers[Rendering::INDEX_BUFFER]->Enable(0);
			Rendering::Renderer::Instance().RenderIndexedMesh(meshType, nElements);
			buffers[Rendering::INDEX_BUFFER]->Disable(0);
		}
		else {
			Rendering::Renderer::Instance().RenderMesh(meshType, nElements);
		}
		
	}
}
